package base

import (
	"gitee.com/wm1998/infra"
	log "github.com/sirupsen/logrus"
	"net"
	"net/rpc"
	"reflect"
)

// Golang内置的RPC服务器端启动器结构体
type GoRPCStarter struct {
	infra.BaseStarter // 包含infra.BaseStarter接口，目的是可以选择性地实现该接口方法
	server            *rpc.Server
}

// 对外暴露一个使用PRC编写的接口注册到RPC服务器的方法-参数：RPC接口
func RpcRegister(ri interface{}) {
	typ := reflect.TypeOf(ri)
	log.Infof("注册基于Golang的RPC实例类型: %s", typ.String()) // 方便日志查看注册了哪些RPC接口
	RpcServer().Register(ri)                          // 将用RPC编写的一些接口注册到RPC服务器端
}

var rpcServer *rpc.Server // RPC服务实例

// 对外暴露获取RCP服务实例的函数
func RpcServer() *rpc.Server {
	Check(rpcServer)
	return rpcServer
}

// 实现了启动器管理器接口的此方法
func (s *GoRPCStarter) Init(ctx infra.StarterContext) {
	s.server = rpc.NewServer() // 构建RPC服务实例
	rpcServer = s.server
}

// 实现了启动器管理器接口的此方法-构建RPC服务器端并以Go程启动
func (s *GoRPCStarter) Start(ctx infra.StarterContext) {
	port := ctx.Props().GetDefault("app.rpc.port", "8082") // 从ctx：基础资源上下文结构体获取系统配置实例
	listener, err := net.Listen("tcp", ":"+port)           // 监听网络端口
	if err != nil {
		log.Panic(err)
	}
	log.Info("Golang基于TCP协议的RPC服务端监听端口：", port)

	// 处理网络连接和请求-基于TCP协议的RPC服务就启动完成了
	go s.server.Accept(listener)
}
